import * as NotifyTemplateApi from '@/api/system/notify/template';
<template>
  <Dialog title="报警规则配置" v-model="dialogVisible" width="1000">
    <el-form :model="form" :rules="rules" ref="formRef" label-width="auto">
      <el-form-item label="规则名称" prop="name">
        <el-input v-model="form.name" placeholder="请输入规则名称" />
      </el-form-item>

      <div v-for="(item, index) in form.alarmTriggerItemList" :key="index" class="trigger-block">
        <div class="trigger-header">
          <h4>触发器 {{ index + 1 }}</h4>

          <el-text type="danger" @click="removeTrigger(index)">删除</el-text>
        </div>

        <div class="trigger-content">
          <el-form-item label="触发器名称" :prop="`alarmTriggerItemList.${index}.name`">
            <el-input v-model="item.name" placeholder="请输入触发器名称" />
          </el-form-item>

          <div class="form-section">
            <h5>报警条件</h5>
            <div style="padding-left: 15px">
              <RuleBuilder
                :rules="item.condition"
                :taskData="taskData"
                :depth="0"
                @change="calcThreshol(item)"
              />
            </div>
          </div>

          <div class="form-section">
            <h5>
              阈值配置
              <el-form-item
                label="告警级数"
                :prop="`alarmTriggerItemList.${index}.thresholdLevelNum`"
                style="margin: 0"
              >
                <el-input-number
                  v-model="item.thresholdLevelNum"
                  :min="1"
                  :max="3"
                  placeholder="1~3"
                  style="width: 100px"
                  @change="calcThreshol(item)"
                /> </el-form-item
            ></h5>

            <div v-if="item.threshol && item.threshol.length > 0">
              <div
                class="signal-threshold-item"
                v-for="sItem of item.threshol"
                :key="sItem.signalId"
              >
                <div class="signal-threshold-name">
                  <span style="color: #e6a23c">{{ sItem.measureName }}</span>
                  {{ sItem.signalLabel + '(' + sItem.label + ')' }}
                </div>

                <div class="signal-threshold-form">
                  <el-form-item
                    v-for="(val, levelIdx) in sItem.thresholdList"
                    :key="levelIdx"
                    :label="`${levelIdx + 1}级阈值`"
                    :prop="`alarmTriggerItemList.${index}.threshol.${sItem.signalId}.thresholdList[${levelIdx}]`"
                    style="margin: 0"
                  >
                    <el-input-number
                      v-model="sItem.thresholdList[levelIdx]"
                      :step="0.1"
                      :min="Number.NEGATIVE_INFINITY"
                      :max="Number.POSITIVE_INFINITY"
                      placeholder="请输入"
                      style="width: 150px"
                    />
                  </el-form-item>
                </div>
              </div>
            </div>
          </div>

          <div class="form-section">
            <h5>防抖配置 </h5>
            <div class="inline-group">
              <el-form-item prop="debounceFlag">
                <el-select style="width: 100px; margin-right: 5px" v-model="item.debounceFlag">
                  <el-option label="开启" :value="1" />
                  <el-option label="关闭" :value="0" />
                </el-select>
              </el-form-item>
              <el-form-item prop="debounceSeconds">
                <el-input-number
                  v-model="item.debounceSeconds"
                  placeholder="防抖时间(秒)"
                  :min="0"
                  style="width: 150px"
                />
              </el-form-item>
              <span>秒内发生</span>
              <el-form-item prop="debounceNum">
                <el-input-number
                  v-model="item.debounceNum"
                  placeholder="防抖次数"
                  :min="1"
                  style="width: 150px"
                />
              </el-form-item>
              <span>次及以上，处理</span>
              <!-- <el-tag type="info" effect="plain" size="large"> 最后一次 </el-tag> -->

              <el-form-item prop="debounceHandle">
                <el-select style="width: 180px" v-model="item.debounceHandle">
                  <el-option label="第一次" :value="1" />
                  <el-option label="最后一次" :value="2" />
                </el-select>
              </el-form-item>
            </div>
          </div>

          <div class="form-section">
            <h5>执行动作</h5>
            <div class="inline-group">
              <span style="margin-left: 0">消息通知</span>
              <!-- <el-form-item prop="pushPlatform">
                <el-select
                  style="width: 180px"
                  v-model="item.pushPlatform"
                  placeholder="请选择消息推送平台"
                  clearable
                >
                  <el-option label="钉钉" value="1" />
                  <el-option label="飞书" value="2" />
                  <el-option label="企业微信" value="3" />
                </el-select>
              </el-form-item> -->
              <el-form-item prop="webhookId">
                <el-select
                  style="width: 180px"
                  v-model="item.webhookId"
                  placeholder="请选择webhook"
                  clearable
                >
                  <el-option
                    v-for="sItem in webhookOptions"
                    :key="sItem.id"
                    :label="sItem.name"
                    :value="sItem.id"
                  />
                </el-select>
              </el-form-item>
              <el-form-item style="margin-left: 5px" prop="notifyTemplateId">
                <el-select
                  style="width: 180px"
                  v-model="item.notifyTemplateId"
                  placeholder="请选择消息通知模板"
                  clearable
                >
                  <el-option
                    v-for="sItem in alarmNotifyTemplateOptions"
                    :key="sItem.id"
                    :label="sItem.name"
                    :value="sItem.id"
                  />
                </el-select>
              </el-form-item>
            </div>
            <div class="message-preview" v-if="item.notifyTemplateId">
              <span style="color: #409eff">消息示例：</span>
              <span>{{
                alarmNotifyTemplateOptions.find((s) => s.id === item.notifyTemplateId)?.content
              }}</span>
            </div>
          </div>
        </div>
      </div>

      <el-button type="primary" :icon="Plus" @click="addTrigger">新增触发器</el-button>
    </el-form>

    <template #footer>
      <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
      <el-button @click="dialogVisible = false">取 消</el-button>
    </template>
  </Dialog>
</template>

<script setup lang="ts">
import { AlarmNotifyTemplateApi } from '@/api/vmiot/alarmnotifytemplate'
import { WebhookApi } from '@/api/vmiot/webhook'
import { AlarmRuleApi } from '@/api/vmiot/alarmrule'
import { Plus } from '@element-plus/icons-vue'
import RuleBuilder from './RuleBuilder.vue'

defineOptions({ name: 'AlarmRuleForm' })

const props = defineProps<{ taskData: any }>()

const emit = defineEmits(['success'])

const { taskData } = toRefs(props)

const message = useMessage()

const dialogVisible = ref(false)
const formLoading = ref(false)

const formRef = ref()

const form = reactive<any>({
  name: '',
  alarmTriggerItemList: [
    {
      name: '',
      thresholdLevelNum: 1,
      debounceFlag: 1,
      debounceSeconds: 0,
      debounceNum: 1,
      debounceHandle: 2,
      pushPlatform: '',
      webhookId: '',
      notifyTemplateId: '',
      condition: {
        operator: 'or',
        conditions: []
      },
      threshol: []
    }
  ]
})

const rules = reactive({
  name: [{ required: true, message: '请输入规则名称', trigger: 'blur' }]
})

const allSignalList = computed(() => {
  return taskData.value.content?.nodes
    .filter((node: any) => node.type === 'output')
    .flatMap((node: any) => {
      return (node.data?.measureData?.signalList || []).map((signal: any) => ({
        ...signal,
        measureName: node.data?.measureData?.name || '',
        measureId: node.id
      }))
    })
})

const alarmNotifyTemplateOptions = ref<any[]>([])
const webhookOptions = ref<any[]>([])

const addTrigger = () => {
  form.alarmTriggerItemList.push({
    name: '',
    thresholdLevelNum: 1,
    debounceFlag: 1,
    debounceSeconds: 0,
    debounceNum: 1,
    debounceHandle: 2,
    pushPlatform: '',
    notifyTemplateId: '',
    condition: {
      operator: 'or',
      conditions: []
    },
    threshol: []
  })
}

const removeTrigger = (index: number) => {
  form.alarmTriggerItemList.splice(index, 1)
}

/** 查询列表 */
const getList = async () => {
  try {
    const templateData = await AlarmNotifyTemplateApi.getAlarmNotifyTemplatePage({
      pageNo: 1,
      pageSize: 100
    })
    alarmNotifyTemplateOptions.value = templateData.list

    const webhookData = await WebhookApi.getWebhookPage({
      pageNo: 1,
      pageSize: 100
    })
    webhookOptions.value = webhookData.list
  } finally {
  }
}

/**
 * 递归出报警条件中的所有信号id和label
 * @param condition
 */
const extractSignalInfos = (
  condition: any
): { signalId: string; label: string; measureId: string }[] => {
  if (!condition) return []

  if (Array.isArray(condition.conditions)) {
    // 递归合并所有子条件
    return condition.conditions.flatMap(extractSignalInfos)
  }

  if (condition.signalId && condition.label) {
    return [
      {
        signalId: condition.signalId,
        label: condition.label,
        measureId: condition.measureId
      }
    ]
  }

  return []
}
/**
 * 根据报警条件计算出阈值配置
 * @param condition
 */
const calcThreshol = (item) => {
  const condition = item.condition

  const infos = extractSignalInfos(condition)
  const uniqueInfos = Array.from(
    new Map(infos.map((info) => [info.signalId + info.label, info])).values()
  )
  const level = Number(item.thresholdLevelNum || 1)

  item.threshol = uniqueInfos
    .map((info) => {
      const signal = allSignalList.value
        .filter((item) => item.measureId === info.measureId)
        .find((s) => s.signalId === info.signalId)
      if (!signal) return null

      // 尝试保留旧的 thresholdList
      const oldThresholdList =
        item.threshol?.find((s) => s.signalId === info.signalId)?.thresholdList || []

      const paddedList = oldThresholdList.slice(0, level)
      while (paddedList.length < level) {
        paddedList.push(0)
      }

      return {
        ...signal,
        label: info.label || '',
        thresholdList: paddedList
      }
    })
    .filter(Boolean) // 去除未匹配成功的 null
}

const getAlarmRule = async () => {
  if (taskData.value.id) {
    const data = await AlarmRuleApi.getAlarmRule(taskData.value.id)
    if (data) {
      form.id = data.id
      form.name = data.name
      form.alarmTriggerItemList = data.alarmTriggerItemList.map((item) => {
        const obj = {
          ...item,
          condition: JSON.parse(item.conditionJson)
        }
        calcThreshol(obj)
        return obj
      })
    }
  }
}

const submitForm = async () => {
  await formRef.value.validate()
  formLoading.value = true
  try {
    const data = form.alarmTriggerItemList.map((item) => ({
      ...item,
      conditionJson: JSON.stringify(item.condition),
      thresholJson: JSON.stringify(
        item.threshol.map((s) => ({
          signalId: s.signalId,
          label: s.label,
          thresholdList: s.thresholdList
        }))
      )
    }))

    const params = {
      id: form.id,
      taskId: taskData.value.id,
      name: form.name,
      alarmTriggerItemList: data
    }

    await AlarmRuleApi.saveAlarmRule(params)

    message.success('提交成功')
    dialogVisible.value = false
    emit('success')
  } finally {
    formLoading.value = false
  }
}

const open = () => {
  dialogVisible.value = true
}

onMounted(() => {
  getList()
  getAlarmRule()
})

defineExpose({ open })
</script>

<style scoped>
.trigger-block {
  margin-bottom: 20px;
  padding: 0 15px;
  border: 1px solid #ebeef5;
  border-radius: 4px;
}
.trigger-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 10px;
  border-bottom: 1px solid #ebeef5;
  padding: 10px 0;
}

.trigger-content {
  padding: 5px 10px;
}
.form-section {
  margin: 15px 0;

  &:last-child {
    margin-bottom: 0;
  }

  h5 {
    margin-bottom: 8px;
    font-size: 15px;

    display: flex;
    justify-content: space-between;
    align-items: center;
  }
}
.inline-group {
  display: flex;
  flex-wrap: wrap;
  align-items: center;

  & > span {
    margin: 0 5px;
  }

  .el-form-item {
    margin-bottom: 0;
  }
}

.signal-threshold-item {
  display: flex;
  align-items: center;
  margin-bottom: 10px;

  .signal-threshold-name {
    flex: 1;
  }

  .signal-threshold-form {
    display: flex;
    align-items: center;
  }
}

.message-preview {
  margin: 10px 0;
  font-size: 13px;
  color: #333;
}
</style>
